/*
Copyright (C) 2009-2010 Xanadu Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "Parties.h"
#include "Party.h"
#include "../../server/Player.h"
#include "PartyMembers.h"
#include "PartyMember.h"
#include "../../tools/PacketCreator.h"
#include "../../server/Channel.h"
#include "World.h"
#include "../../server/Event.h"
#include "../../server/Events.h"
#include "../../server/Map.h"
#include "../../tools/MySQLM.h"
string valstr(int id);

void Parties::create(Player* player) {
	if(player->getParty() != 0 || player->getLevel() < 10)
		return;
	Party* party = new Party(world, player);
	player->setParty(party);
	parties[party->getID()] = party;
	player->send(PacketCreator().createParty(party->getID()));
}

void Parties::leave(Player* player) {
	if (player->getParty() == 0) {
		return;
	}
	if (player->getMap()->getEvent() != 0 && player->getMap()->getEvent()->getParty()) {
		player->getChannel()->getEvents()->deleteEvent(player->getMap()->getEvent()->getName());
	}
	Party* party = player->getParty();
	if (party->getLeader() == player->getID()) {
		party->getMembers()->send(PacketCreator().removeParty(party->getID(), player->getID()));
		parties.erase(party->getID());
		delete party;
	}
	else {
		PartyMember* member = party->getMembers()->getMember(player->getID());
		party->getMembers()->send(PacketCreator().leaveParty(party, member));
		party->removeMember(player->getID());
		player->setParty(0);
	}
}

void Parties::join(Player* player, int partyid) {
	if (player->getPartyInvite() != partyid || player->getParty() != 0) {
		player->setPartyInvite(0);
		return;
	}
	player->setPartyInvite(0);
	Party* party = getParty(partyid);
	if (party == 0) {
		return;
	}
	if(party->getMembers()->getMembers()->size() == 6) {
		player->send(PacketCreator().partyError(0x11));
		return;
	}
	party->getMembers()->addMember(player);
	player->setParty(party);
	PartyMember* member = party->getMembers()->getMember(player->getID());
	party->getMembers()->send(PacketCreator().joinParty(party, member));
	party->getMembers()->send(PacketCreator().updatePartyHp(player), player->getMap(), player);
	hash_map <int, Player*>* players = party->getMembers()->getPlayers();
	for(hash_map<int, Player*>::iterator iter = players->begin(); iter != players->end(); iter++) {
		if(iter->second->getMap() == player->getMap() && iter->second != player)
			player->send(PacketCreator().updatePartyHp(iter->second));
	}
}

void Parties::invite(Player* player, string& name) {
	if (player->getParty() == 0 || player->getParty()->getLeader() != player->getID() || player->getName() == name) {
		return;
	}
	Player* invited = player->getChannel()->getPlayers()->getPlayerByName(name);
	if (invited == 0) {
		player->send(PacketCreator().partyError(18));
		return;
	}
	if (invited->getParty() != 0) {
		player->send(PacketCreator().partyError(16));
		return;
	}
	if (invited->getPartyInvite() != 0) {
		player->send(PacketCreator().partyError(22, name));
		return;
	}
	Party* party = player->getParty();
	invited->setPartyInvite(party->getID());
	invited->send(PacketCreator().inviteParty(party->getID(), player->getName()));
}

void Parties::expel(Player* player, int playerid) {
	Party* party = player->getParty();
	if(party == 0 || party->getLeader() != player->getID() || player->getID() == playerid) {
		return;
	}
	PartyMember* member = party->getMembers()->getMember(playerid);
	if (member == 0) {
		return;
	}
	party->getMembers()->send(PacketCreator().leaveParty(party, member, true));
	party->removeMember(playerid);
	Player* expelled = player->getWorld()->getPlayerByID(playerid);
	if (expelled != 0) {
		expelled->setParty(0);
		if (player->getMap()->getEvent() != 0 && player->getMap()->getEvent()->getParty() && expelled->getMap()->getEvent() == player->getMap()->getEvent()) {
			player->getChannel()->getEvents()->deleteEvent(player->getMap()->getEvent()->getName());
		}
	}
}

void Parties::changeLeader(Player* player, int playerid) {
	Party* party = player->getParty();
	if (party == 0 || party->getLeader() != player->getID() || !player->getWorld()->isPlayerConnected(playerid)) {
		return;
	}
	if (player->getWorld()->getPlayerByID(playerid)->getMap() != player->getMap()) {
		return;
	}
	party->setLeader(playerid);
	party->getMembers()->send(PacketCreator().changeLeader(playerid));
}

Party* Parties::getParty(int id) {
	if (parties.find(id) == parties.end()) {
		mysqlpp::Connection::thread_start();
		mysqlpp::Connection* conn = MySQL::getInstance()->getPool()->grab();
		mysqlpp::StoreQueryResult res = conn->query("select leader from party where id = " + valstr(id) + " and world = " + valstr(world->getID())).store();
		if (res.empty()) {
			return 0;
		}
		Party* party = new Party(id, atoi(res[0][0].c_str()));
		res = conn->query("select id, name, job, level from characters where party = " + valstr(id)).store();
		for(int i = 0; i < (int)res.num_rows(); i++) {
			PartyMember* member = new PartyMember();
			member->setID(atoi(res[i][0].c_str()));
			member->setName(string(res[i][1].c_str()));
			member->setJob(atoi(res[i][2].c_str()));
			member->setLevel(atoi(res[i][3].c_str()));
			member->setChannel(-2);
			member->setMap(999999999);
			party->getMembers()->addMember(member);
		}
		parties[id] = party;
		MySQL::getInstance()->getPool()->release(conn);
		mysqlpp::Connection::thread_end();
	}
	return parties[id];
}